package net.sahv.bdyz.shiro;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

import net.sahv.bdyz.model.Admin;
import net.sahv.bdyz.service.AdminRoleService;
import net.sahv.bdyz.service.AdminService;
import net.sahv.bdyz.service.RoleAuthorityService;
   
public class MyRealm extends AuthorizingRealm {  
    /** 
     * 为当前登录的Subject授予角色和权限 
     * @see 经测试:本例中该方法的调用时机为需授权资源被访问时 
     * @see 经测试:并且每次访问需授权资源时都会执行该方法中的逻辑,这表明本例中默认并未启用AuthorizationCache 
     * @see 个人感觉若使用了Spring3.1开始提供的ConcurrentMapCache支持,则可灵活决定是否启用AuthorizationCache 
     * @see 比如说这里从数据库获取权限信息时,先去访问Spring3.1提供的缓存,而不使用Shior提供的AuthorizationCache 
     */  
	@Autowired
	private AdminService adminService;
	@Autowired
	private AdminRoleService adminRoleService;
	@Autowired
	private RoleAuthorityService roleAuthorityService;
	
    @Override  
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals){  
        //获取当前登录的用户名,等价于(String)principals.fromRealm(this.getName()).iterator().next()  
      List<String> roleList = new ArrayList<String>();  
      List<String> permissionList = new ArrayList<String>();  
//      //从数据库中获取当前登录用户的详细信息  
      Admin admin=null;
      Subject currentUser = SecurityUtils.getSubject();  
      if(null != currentUser){  
          Session session = currentUser.getSession();  
          if(null != session){  
        	  admin= (Admin) session.getAttribute("currentUser");  
          }  
      }
      if(null != admin){
    	  SimpleAuthorizationInfo simpleAuthorInfo = new SimpleAuthorizationInfo();  
    	  //查询登录用户的所有角色
    	  //List<Map<String, Object>> roles = AdminUserRolesService.selectRolesByAdminid(admin.getaId());
    	  List<Map<String, Object>> roles=adminRoleService.selectRolesByAdminId(admin.getaId());

          if(null!=roles && roles.size()>0){  
              for(int i=0;i<roles.size();i++){  
            	  //添加角色到角色集合
                  roleList.add(roles.get(i).get("R_NAME").toString());  
//                //查询角色的权限
                  List<Map<String, Object>> quanxian = roleAuthorityService.selectAuthorityByRoleId(Integer.parseInt(roles.get(i).get("R_ID").toString()));
                  
                  if(null!=quanxian && quanxian.size()>0){  
//                      //获取权限  
                      for(int y=0;y<quanxian.size();y++){  
                              permissionList.add(quanxian.get(y).get("RA_AUTHORITY_NAME").toString());  
                      }  
                  }  
              } 
          } 
          simpleAuthorInfo.addRoles(roleList);  
          simpleAuthorInfo.addStringPermissions(permissionList);  
          return simpleAuthorInfo; 
      }else{  
    	  return null;
      }  

    }  
   
       
    /** 
     * 验证当前登录的Subject 
     * @see 经测试:本例中该方法的调用时机为LoginController.login()方法中执行Subject.login()时 
     */  
    @Override  
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {  
        //获取基于用户名和密码的令牌  
        //实际上这个authcToken是从LoginController里面currentUser.login(token)传过来的  
        //两个token的引用都是一样的,本例中是org.apache.shiro.authc.UsernamePasswordToken@33799a1e  
        UsernamePasswordToken token = (UsernamePasswordToken)authcToken;  
      //  System.out.println("验证当前Subject时获取到token为" + ReflectionToStringBuilder.toString(token, ToStringStyle.MULTI_LINE_STYLE));  
        Admin admin = adminService.findByname(token.getUsername());  
      if(null != admin){  
          AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(admin.getaUsername(), admin.getaPassword(), getName()); 
          List<Map<String, Object>> adminRole=adminRoleService.selectRolesByAdminId(admin.getaId());
          this.setSession("currentUser", admin);
          this.setSession("currentRole", adminRole.get(0));
          return authcInfo;  
      }else{  
          return null;  
      }  
       
    }  
       
    /** 
     * 将一些数据放到ShiroSession中,以便于其它地方使用 
     * @see 比如Controller,使用时直接用HttpSession.getAttribute(key)就可以取到 
     */  
    private void setSession(Object key, Object value){  
        Subject currentUser = SecurityUtils.getSubject();  
        if(null != currentUser){  
            Session session = currentUser.getSession();  
            System.out.println("Session默认超时时间为[" + session.getTimeout() + "]毫秒");  
            if(null != session){  
                session.setAttribute(key, value);  
            }  
        }  
    }  
}